﻿namespace _24_Hour_Blogger.Models
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using _24_Hour_Blogger.Models.Content;
    using _24_Hour_Blogger.Models.Repository;
    using Rally_MvvmC.Exceptions;
    using Rally_MvvmC.Exceptions.Server;
    using BloggerLibrary = _24_Hour_Blogger.Library;
    using Rally_MvvmC.Library;

    public class DataStore : IDataStore
    {
        private ContentEntitiesContainer contentEntities;
        private sjf_24_hour_blogger_repositoryEntities repositoryEntities;

        public DataStore()
        {
        }

        public ContentEntitiesContainer ContentEntities
        {
            get
            {
                if (this.contentEntities == null)
                {
                    this.contentEntities = new ContentEntitiesContainer();
                }

                return this.contentEntities;
            }

            private set
            {
                if (value == null)
                {
                    if (this.contentEntities != null)
                    {
                        this.contentEntities.Dispose();
                        this.contentEntities = null;
                    }
                }
                else
                {
                    this.contentEntities = value;
                }
            }
        }

        public sjf_24_hour_blogger_repositoryEntities RepositoryEntities
        {
            get
            {
                if (this.repositoryEntities == null)
                {
                    this.repositoryEntities = new sjf_24_hour_blogger_repositoryEntities();
                }

                return this.repositoryEntities;
            }

            private set
            {
                if (value == null)
                {
                    if (this.repositoryEntities != null)
                    {
                        this.repositoryEntities.Dispose();
                        this.repositoryEntities = null;
                    }
                }
                else
                {
                    this.repositoryEntities = value;
                }
            }
        }

        public static DataStore CreateStore()
        {
            return new DataStore();
        }


        public void Put<DataStoreType, ViewModelClass, EntityClass>(DbContext dataContext, ViewModelClass item, int userId, bool updateChildren, bool useTransaction)
            where DataStoreType : IDataStore
            where EntityClass : class
            where ViewModelClass : ViewModelBase<DataStoreType, EntityClass>
        {
            if (item.ScheduleForDelete)
            {
                dataContext.Entry(item.GetEntity()).State = System.Data.Entity.EntityState.Deleted;
            }
            else
            {
                if (item.Id <= 0 || item.ForceSaveAsNew)
                {
                    if (updateChildren)
                    {
                        DataStore.SetForSaveChildViewModels(item, dataContext, userId);
                    }
                    else
                    {
                        DbEntityEntry dataEntityEntry = dataContext.Entry<EntityClass>(item.Entity);
                        if (dataEntityEntry.State != System.Data.Entity.EntityState.Detached)
                        {
                            dataEntityEntry.State = System.Data.Entity.EntityState.Added;
                        }
                        else
                        {
                            dataContext.Set<EntityClass>().Add(item.Entity);
                        }
                    }

                    item.CreatedByUserId = userId;
                    item.CreatedDate = DateTime.Now;
                    item.UpdatedDate = DateTime.Now;
                    item.UpdatedByUserId = userId;
                }
                else
                {
                    item.UpdatedDate = DateTime.Now;
                    item.UpdatedByUserId = userId;

                    item.CreatedByUserId = userId;
                    item.CreatedDate = DateTime.Now;

                    if (updateChildren)
                    {
                        DataStore.SetForSaveChildViewModels(item, dataContext, userId);
                    }
                    else
                    {
                        var entry = dataContext.Entry(item.GetEntity());
                        dataContext.Entry(item.GetEntity()).State = System.Data.Entity.EntityState.Modified;
                    }
                }
            }

            if (!useTransaction)
            {
                dataContext.SaveChanges();
            }
        }

        /// <summary>
        /// Dispose of underlying database resources. 
        /// </summary>
        public void Dispose()
        {
            this.ContentEntities = null;
            this.RepositoryEntities = null;
        }

        private static void SetForSaveChildViewModels(IViewModel item, DbContext dbContext, int userId)
        {
            if (item.ScheduleForDelete)
            {
                dbContext.Entry(item.GetEntity()).State = System.Data.Entity.EntityState.Deleted;
            }
            else
            {
                if (item.Id > 0)
                {
                    dbContext.Entry(item.GetEntity()).State = System.Data.Entity.EntityState.Modified;
                    item.UpdatedDate = DateTime.Now;
                    item.UpdatedByUserId = userId;
                }
                else
                {
                    if (dbContext.Entry(item.GetEntity()).State != EntityState.Detached)
                    {
                        dbContext.Entry(item.GetEntity()).State = System.Data.Entity.EntityState.Added;
                    }
                    else
                    {
                        dbContext.Set(item.GetEntity().GetType()).Add(item.GetEntity());
                    }

                    item.CreatedByUserId = userId;
                    item.CreatedDate = DateTime.Now;
                    item.UpdatedDate = DateTime.Now;
                    item.UpdatedByUserId = userId;

                }

                var collection = item.GetModified();
                foreach (var viewModel in collection)
                {
                    if (viewModel != null)
                    {
                        SetForSaveChildViewModels(viewModel, dbContext, userId);
                    }
                }
            }

        }
    }
}
